package com.hd.service.activiti.example.impl;

import com.hd.commons.exception.MyException;
import com.hd.dao.BaseDao;
import com.hd.entity.activiti.BaseVO;
import com.hd.entity.activiti.CommentEntity;
import com.hd.entity.activiti.ProcessInstanceEntity;
import com.hd.entity.activiti.example.Leave;
import com.hd.entity.sys.User;
import com.hd.service.activiti.ActStartRightService;
import com.hd.service.activiti.ActivitiService;
import com.hd.service.activiti.CommentEntityService;
import com.hd.service.activiti.example.LeaveService;
import com.hd.service.impl.BaseServiceImpl;
import com.hd.service.sys.UserService;
import com.hd.util.StringUtils;
import com.hd.util.result.PageInfo;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;
@Service("leaveService")
public class LeaveServiceImpl extends BaseServiceImpl<Leave, String> implements LeaveService {
	@Autowired
	private BaseDao<Leave,String>leaveDao;
	@Autowired
	private IdentityService identityService;
	@Autowired
	private RepositoryService repositoryService;
	@Autowired
	private RuntimeService runtimeService;
	@Autowired
	private ActivitiService activitiService;
	@Autowired
	private ActStartRightService actStartRightService;
	@Autowired
	private BaseDao<ProcessInstanceEntity,String>processInstanceEntityDao;
	@Autowired
	private CommentEntityService commentEntityService;
	@Autowired
	private UserService userService;
	@Override
	public Serializable save(Leave leave) {
		try {
			leave.setId(UUID.randomUUID().toString());
			return this.add(leave);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	@Override
	public void update(Leave leave) {
		try {
			this.saveOrUpdate(leave);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void deleteByProcessInstanceId(String processInstanceId) {
		String hql="delete from Leave where processInstanceId=?";
		leaveDao.execute(hql, processInstanceId);
	}

	@Override
	public Leave getByProcessInstanceId(String processInstanceId) {
		String hql="from Leave where processInstanceId=?";
		List<Leave>leaves=leaveDao.find(hql, processInstanceId);
		if(leaves.size()>0) {
			return leaves.get(0);
		}
		return null;
	}

	@Override
	public String startProcessInstance(String processDefKey,Leave leave) {
		//判断是否有权限启动流程
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefKey).latestVersion().singleResult();
		Boolean hasAuthenticated = actStartRightService.hasAuthenticated(processDefinition.getId(), leave.getUserid());
		if(!hasAuthenticated) {
			leaveDao.delete(leave);
			throw new MyException("你没有权限启动该流程");
		}
		  // 用来设置启动流程的人员ID，引擎会自动把用户ID保存到activiti:initiator中
        identityService.setAuthenticatedUserId(leave.getUserid().toString());
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("entity", leave);
        variables.put("objId", leave.getId());
        variables.put("prevUserid", leave.getPrevUserid());
        String businessKey = leave.getBusinessKey_();
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefKey, businessKey, variables);
        String processInstanceId = processInstance.getId();
        leave.setProcessInstanceId(processInstanceId);
        this.leaveDao.update(leave);
        //最后要设置null，就是这么做，还没研究为什么
        this.identityService.setAuthenticatedUserId(null);
        return processInstanceId;
	}

	@Override
	public void selectDataGrid(PageInfo pageInfo) {
		 String hql="from Leave where 1=1 and userid=?";
	        Map<String,Object>condition=pageInfo.getCondition();
	        List<Object> params=new ArrayList<Object>();
	        params.add(condition.get("userid"));
				if(!StringUtils.isNull(condition.get("status"))) {
	            hql+=" and status=?";
	            params.add(condition.get("status"));
	        }
				if(!StringUtils.isNull(condition.get("title"))) {
	            hql+=" and title=?";
	            params.add(condition.get("title"));
	        }
				if(!StringUtils.isNull(condition.get("processInstanceId"))) {
	            hql+=" and processInstanceId=?";
	            params.add(condition.get("processInstanceId"));
	        }
	        if(condition.get("leaveDateStart")!=null) {
	            hql+=" and leaveDate >=?";
	            params.add(condition.get("leaveDateStart"));
	        }
	        if(condition.get("leaveDateEnd")!=null) {
	            hql+=" and leaveDate <=?";
	            params.add(condition.get("leaveDateEnd"));
	        }
	        hql+=" order by status asc,leaveDate desc";
	        List<Leave> leaves=leaveDao.findPage(hql, pageInfo.getNowpage(), pageInfo.getPagesize(),params);
	        //设置任务执行人
	        if(leaves.size()>0) {
	        	for(Leave leave:leaves) {
	        		if(leave.getStatus().equals(BaseVO.APPROVAL_ADJUST)||leave.getStatus().equals(BaseVO.PENDING)) {
	        			Map<String, Object> map = activitiService.findTodoTaskAssigneeOrCandidateUsers(leave.getProcessInstanceId());
	        			String taskAssigneeOrCandidateUsers = (String) map.get("userNames");
	        			leave.setAssigneeOrCandidateUser(taskAssigneeOrCandidateUsers);
	        			leave.setTaskName((String)map.get("taskName"));
	        		}
	        	}
	        }
	        pageInfo.setRows(leaves);
			String countHql="select count(*) "+hql;
			int total=Integer.parseInt(leaveDao.getCountByList(countHql,params).toString());
	        pageInfo.setTotal(total);
		
	}

	@Override
	public Leave get(String id) {
		return leaveDao.get(Leave.class, id);
	}

	@Override
	public void delete(String id) {
		leaveDao.delete(Leave.class, id);
	}

	/**
	 * 作废流程
	 */
	@Override
	public void deleteLeaveProcess(String processInstanceId) {
		ProcessInstanceEntity processInstanceEntity = processInstanceEntityDao.get(ProcessInstanceEntity.class, processInstanceId);
		if((processInstanceEntity.getStatus()==processInstanceEntity.FAIL_STATUS)||processInstanceEntity.getStatus()==processInstanceEntity.COMPLETE_STATUS) {
			throw new MyException("流程【"+processInstanceId+"】已审批结束，不能作废");
		}
		if(processInstanceEntity.getStatus()!=processInstanceEntity.INVALID) {
			runtimeService.suspendProcessInstanceById(processInstanceId);//挂起流程
			runtimeService.deleteProcessInstance(processInstanceId,"作废流程");//删除流程
			String hql="update  Leave set status=? where processInstanceId=?";
			leaveDao.execute(hql, BaseVO.INVALID,processInstanceId);
			 hql="update ProcessInstanceEntity set status=? where processInstanceId=?";
			 processInstanceEntityDao.execute(hql,ProcessInstanceEntity.INVALID_STATUS,processInstanceId);
			 doInvalidComment(processInstanceEntity.getUserid(),processInstanceId);
		}
	}
	  //作废流程信息
		protected void doInvalidComment(String userId,String processInstanceId){
			CommentEntity commentEntity=new CommentEntity();
			commentEntity.setTime(new Date());
			commentEntity.setType(CommentEntity.COMMENT_INVALID);
			User user = userService.get(userId);
			if (user != null) {
				commentEntity.setUserName(user.getName());
			}
			commentEntity.setUserid(userId);
			commentEntity.setProcessInstanceId(processInstanceId);
			String	comment=user.getName()+"作废流程【"+processInstanceId+"】";
			commentEntity.setComment(comment);
			commentEntityService.save(commentEntity);
		}

		/**
		 * 修改审批状态
		 */
		@Override
		public void updateStatus(String id, Integer status) {
			String hql="update Leave set status=? where id=?";
			leaveDao.execute(hql, status,id);
			
		}
}
